﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Media;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.Helpers;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;

namespace TuanHA_Monk_Special_Edition_Extreme_PvP
{
    public partial class Classname
    {
        #region Attackable

        private bool Attackable(WoWUnit target)
        {
            if (target != null && SpecialUnit.Contains(target.Entry))
            {
                return true;
            }

            if (!ValidUnit(target))
            {
                return false;
            }

            if (!IsEnemy(target))
            {
                return false;
            }

            if (Invulnerable(target))
            {
                return false;
            }

            if (DebuffCCBreakonDamage(target))
            {
                return false;
            }


            return true;
        }

        private bool Attackable(WoWUnit target, int range)
        {
            if (target == null)
            {
                return false;
            }

            if (SpecialUnit.Contains(target.Entry))
            {
                return true;
            }

            if (!ValidUnit(target))
            {
                return false;
            }

            if (DebuffCCBreakonDamage(target))
            {
                return false;
            }

            if (range > 5 && !target.InLineOfSpellSight)
            {
                return false;
            }

            if (range <= 5 && !target.IsWithinMeleeRange)
            {
                return false;
            }

            if (range > 5 && target.Distance2D - target.BoundingRadius > range)
            {
                return false;
            }

            if (!IsEnemy(target))
            {
                return false;
            }

            if (Invulnerable(target))
            {
                return false;
            }

            return true;
        }

        private bool AttackableValid(WoWUnit target)
        {
            if (target.Distance < 40 && !Invulnerable(target) &&
                !DebuffCCBreakonDamage(target) && IsEnemy(target) &&
                target.InLineOfSpellSight)
            {
                return true;
            }
            return false;
        }

        #endregion

        #region  BattleStandard

        public Composite UseBattleStandard()
        {
            return
                new Decorator(
                    ret =>
                    THSettings.Instance.HealthStone &&
                    Me.Combat &&
                    Me.HealthPercent < THSettings.Instance.HealthStoneHP &&
                    Me.CurrentTarget != null &&
                    Me.CurrentTarget.CurrentHealth > Me.HealthPercent &&
                    Me.CurrentMap.IsBattleground,
                    new Action(delegate
                                   {
                                       if (Me.IsAlliance)
                                       {
                                           WoWItem bs = Me.BagItems.FirstOrDefault(o => o.Entry == 18606);
                                           //18606 Alliance Battle Standard

                                           if (!Me.HasAura("Alliance Battle Standard") && bs != null &&
                                               bs.CooldownTimeLeft.TotalMilliseconds <= MyLatency)
                                           {
                                               bs.Use();
                                               //Lua.DoString("RunMacroText(\"/5 Used Healthstone\")");
                                               //Lua.DoString("RunMacroText(\"/s Used Battle Standard\")");
                                               Logging.Write("Use Battle Standard at " + Me.HealthPercent + "%");
                                           }
                                       }

                                       if (Me.IsHorde)
                                       {
                                           WoWItem bs = Me.BagItems.FirstOrDefault(o => o.Entry == 18607);
                                           //18606 Horde Battle Standard

                                           if (!Me.HasAura("Horde Battle Standard") && bs != null &&
                                               bs.CooldownTimeLeft.TotalMilliseconds <= MyLatency)
                                           {
                                               bs.Use();
                                               //Lua.DoString("RunMacroText(\"/5 Used Healthstone\")");
                                               //Lua.DoString("RunMacroText(\"/s Used Battle Standard\")");
                                               Logging.Write("Use Battle Standard at " + Me.HealthPercent + "%");
                                           }
                                       }

                                       return RunStatus.Failure;
                                   })
                    );
        }

        #endregion

        #region CastSpell

        public static DateTime HoldRotationWhileFlying = DateTime.Now;
        public static WoWUnit LastCastUnit;
        public static WoWUnit LastCastUnitSoothingMist = Me;
        public static DateTime LastCastTime = DateTime.Now;
        public string LastCastSpell = "";
        private string _writeReason;

        public void CastSpell(string spellName, WoWUnit u, string reason = "")
        {
            //if (u == null || !u.IsValid)
            //{
            //    return;
            //}

            while (_gcdReady > DateTime.Now && !NoGCDSpells.Contains(spellName))
            {
            }

            SpellManager.Cast(spellName, u);

            //UpdateCooldown(spellName);

            string barTwo;
            if (Me.HasAura("Stance of the Wise Serpent"))
            {
                barTwo = "Chi: " + Me.CurrentChi + " Mana: " + Math.Round(Me.ManaPercent);
            }
            else
            {
                barTwo = "Chi: " + Me.CurrentChi + " Energy: " + Math.Round(Me.EnergyPercent);
            }

            string unitLogName;
            if (u == Me)
            {
                unitLogName = "Myself";
            }
            else if (u.IsPlayer)
            {
                unitLogName = u.Class.ToString();
            }
            else
            {
                unitLogName = u.Name;
            }

            _writeReason = "";
            if (reason != "")
            {
                _writeReason = " (" + reason + ")";
            }

            Color colorlog;
            if (AttackSpells.Contains(spellName))
            {
                colorlog = Colors.Yellow;
            }

            else if (DefendSpells.Contains(spellName))
            {
                colorlog = Colors.Green;
            }
            else if (SpecialSpells.Contains(spellName))
            {
                colorlog = Colors.OrangeRed;
            }
            else
            {
                colorlog = Colors.GreenYellow;
            }

            Logging.Write(colorlog, DateTime.Now.ToString("ss:fff") + " - hp: " +
                                    Math.Round(Me.HealthPercent) + " - " + barTwo + " - " +
                                    unitLogName + " - " +
                                    Math.Round(u.Distance, 2) + "y - " +
                                    Math.Round(u.HealthPercent) + " hp - " + spellName + _writeReason);

            LastCastTime = DateTime.Now;
            LastCastSpell = spellName;
            LastCastUnit = u;

            TickMilisecond = DateTime.Now;

            if (!NoGCDSpells.Contains(spellName))
            {
                UpdateGCD();
            }
        }

        #endregion

        #region CanCleanse

        public bool CanCleanse(WoWAura aura)
        {
            //if (aura == null)
            //    return false;

            //if (aura.Spell.DispelType == WoWDispelType.Disease || aura.Spell.DispelType == WoWDispelType.Magic ||
            //    aura.Spell.DispelType == WoWDispelType.Poison)
            if (aura.Spell.DispelType != WoWDispelType.None)
            {
                //Logging.Write("CanCleanse: " + aura.Name + " - " + aura.SpellId);
                return true;
            }
            return false;
        }

        #endregion

        #region CanUseEquippedItem

        //Thank Apoc
        private static bool CanUseEquippedItem(WoWItem item)
        {
            // Check for engineering tinkers!
            var itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
            if (string.IsNullOrEmpty(itemSpell))
                return false;


            return item.Usable && item.Cooldown <= 0;
        }

        #endregion

        #region ConstantFace

        public void ConstantFace(WoWUnit unit)
        {
            if (THSettings.Instance.AutoFace && !IsOverrideModeOn && !Me.IsSafelyFacing(unit))
            {
                unit.Face();
                WoWMovement.ConstantFace(unit.Guid);
            }
        }

        #endregion

        #region CountDebuff

        public static double CountDebuff(WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                int numberofDebuff =
                    u.Debuffs.Values.Count(
                        debuff =>
                        (debuff.Spell.DispelType == WoWDispelType.Magic ||
                         debuff.Spell.DispelType == WoWDispelType.Poison ||
                         debuff.Spell.DispelType == WoWDispelType.Disease));

                return numberofDebuff;
            }
        }

        public static double CountDebuffMagic(WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                int numberofDebuff =
                    u.Debuffs.Values.Count(
                        debuff => (debuff.Spell.DispelType == WoWDispelType.Magic));

                return numberofDebuff;
            }
        }

        //public static double CountDebuffCanCleanse(WoWUnit u)
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        int numberofDebuff =
        //            u.Debuffs.Values.Count(debuff => ListAllCanCleanseDebuff.Contains("[" + debuff.SpellId + "]"));
        //        return numberofDebuff;
        //    }
        //}

        //public double CountDebuffRootandSnare(WoWUnit u)
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        //foreach (var Debuff in u.Debuffs)
        //        //{
        //        //    if(ListSnare.Contains("[" + Debuff.Value.SpellId + "]") || 
        //        //        ListRoot.Contains("[" + Debuff.Value.SpellId + "]"))
        //        //    {
        //        //        numberofDebuff = numberofDebuff + 1;
        //        //    }
        //        //}

        //        //int numberofDebuff =
        //        //    u.ActiveAuras.Values.Count(
        //        //        debuff =>
        //        //        (ListSnare.Contains("[" + debuff.SpellId + "]") || 
        //        //        ListRoot.Contains("[" + debuff.SpellId + "]")));
        //        //        //(debuff.Spell.Mechanic == WoWSpellMechanic.Snared ||
        //        //         //debuff.Spell.Mechanic == WoWSpellMechanic.Rooted));

        //        return
        //            u.Debuffs.Count(
        //                debuff =>
        //                ListSnare.Contains("[" + debuff.Value.SpellId + "]") ||
        //                ListRoot.Contains("[" + debuff.Value.SpellId + "]"));
        //    }
        //}

        public double CountDebuffRootandSnareMechanic(WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                return
                    u.ActiveAuras.Values.Count(
                        debuff =>
                        (debuff.Spell.Mechanic == WoWSpellMechanic.Snared ||
                         debuff.Spell.Mechanic == WoWSpellMechanic.Rooted));
            }
        }

        #endregion

        #region CountDPSTarget

        //private int CountDPSTarget(WoWUnit target)
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
        //        {
        //            return NearbyUnFriendlyPlayers.Count(
        //                unit =>
        //                unit.GotTarget &&
        //                unit.CurrentTarget == target &&
        //                (TalentSort(unit) >= 2 &&
        //                 TalentSort(unit) <= 3 &&
        //                 unit.Location.Distance(target.Location) < 40 ||
        //                 TalentSort(unit) == 1 &&
        //                 unit.Location.Distance(target.Location) < 15) &&
        //                !DebuffCC(unit));
        //        }
        //        return NearbyUnFriendlyUnits.Count(
        //            unit =>
        //            unit.GotTarget &&
        //            unit.CurrentTarget == target &&
        //            !DebuffCC(unit));
        //    }
        //}

        #endregion

        #region CountMagicDPSTarget

        //private int CountMagicDPSTarget(WoWUnit target)
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
        //        {
        //            return NearbyUnFriendlyPlayers.Count(
        //                unit =>
        //                unit.GotTarget &&
        //                unit.CurrentTarget == target &&
        //                TalentSort(unit) == 3 &&
        //                unit.Location.Distance(target.Location) < 40 &&
        //                !DebuffCC(unit));
        //        }
        //        return NearbyUnFriendlyUnits.Count(
        //            unit =>
        //            unit.GotTarget &&
        //            unit.CurrentTarget == target &&
        //            unit.Location.Distance(target.Location) < 40 &&
        //            !DebuffCC(unit));
        //    }
        //}

        #endregion

        #region CountMeleeDPSTarget

        private int CountMeleeDPSTarget(WoWUnit target)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
                {
                    return NearbyUnFriendlyPlayers.Count(
                        unit =>
                        unit.GotTarget &&
                        unit.CurrentTarget == target &&
                        TalentSort(unit) == 1 &&
                        unit.Location.Distance(target.Location) < 15 &&
                        !DebuffCC(unit));
                }
                return NearbyUnFriendlyUnits.Count(
                    unit =>
                    unit.GotTarget &&
                    unit.CurrentTarget == target &&
                    unit.Location.Distance(target.Location) < 15 &&
                    !DebuffCC(unit));
            }
        }

        #endregion

        #region CountPhysicDPSTarget

        //private int CountPhysicDPSTarget(WoWUnit target)
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
        //        {
        //            return NearbyUnFriendlyPlayers.Count(
        //                unit =>
        //                unit.GotTarget &&
        //                unit.CurrentTarget == target &&
        //                (TalentSort(unit) == 2 &&
        //                 unit.Location.Distance(target.Location) < 40 ||
        //                 TalentSort(unit) == 1 &&
        //                 unit.Location.Distance(target.Location) < 25) &&
        //                !DebuffCC(unit));
        //        }
        //        return NearbyUnFriendlyUnits.Count(
        //            unit =>
        //            unit.GotTarget &&
        //            unit.CurrentTarget == target &&
        //            unit.Location.Distance(target.Location) < 15 &&
        //            !DebuffCC(unit));
        //    }
        //}

        #endregion

        #region CountEneyNeary

        private double CountEneyNeary(WoWObject unitCenter, float distance)
        {
            return
                NearbyUnFriendlyUnits.Where(
                    unit =>
                    unitCenter.Location.Distance(unit.Location) <= distance &&
                    unit.Combat && !unit.IsPet &&
                    (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                     unit.IsTargetingMeOrPet)).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        #endregion

        #region CountEneyNearyMeFacing

        private double CountEneyNearyMeFacing(int distance)
        {
            return
                FarFriendlyUnits.Where(
                    unit =>
                    Me.IsFacing(unit) &&
                    Attackable(unit, distance) &&
                    !unit.IsPet &&
                    (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                     unit.IsTargetingMeOrPet)).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        #endregion

        #region CountEneyNearyWorthDropStatue

        private double CountEneyNearyWorthDropStatue(int distance)
        {
            return
                NearbyUnFriendlyUnits.Where(
                    unit =>
                    Me.IsFacing(unit) &&
                    Attackable(unit, distance) &&
                    !unit.IsPet
                    ).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        #endregion

        #region CountEneyNearyObject

        //private double CountEneyNearyWoWPoint(WoWPoint unitCenter, float distance)
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            unitCenter.Distance(unit.Location) <= distance).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountEnemyFromPoint

        //private double CountEnemyFromPoint(WoWPoint pointCenter, float radius)
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            pointCenter.Distance(unit.Location) <= radius &&
        //            unit.Combat).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountEneyTargettingUnit

        //private double CountEneyTargettingUnit(WoWUnit target, float distance)
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            unit.Distance < distance &&
        //            unit.GotTarget &&
        //            unit.Level <= target.Level + 3 &&
        //            //unit.Combat && 
        //            !unit.IsPet &&
        //            unit.CurrentTarget == target //&&
        //            //DebuffCC(unit) <= MyLatency
        //            ).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountFriendlyInLineNeedHeal

        private double CountFriendlyInLine(WoWObject unitTarget, float distance, double healthPercent)
        {
            return (from WoWPlayer player in NearbyFriendlyPlayers
                    let playermidpoint =
                        WoWMathHelper.CalculatePointFrom(Me.Location, unitTarget.Location,
                                                         (float)unitTarget.Distance - (float)player.Distance)
                    where
                        unitTarget.Distance < distance && player.Distance < unitTarget.Distance &&
                        player.Location.Distance(playermidpoint) <= 8 && player.HealthPercent <= healthPercent
                    select player).Count();

            //var totalUnit = 0;
            //foreach (WoWPlayer player in NearbyFriendlyPlayers)
            //{
            //    var playermidpoint = WoWMathHelper.CalculatePointFrom(Me.Location, unitTarget.Location,
            //                                                          (float)unitTarget.Distance -
            //                                                          (float)player.Distance);
            //    if (unitTarget.Distance < distance && player.Distance < unitTarget.Distance &&
            //        player.Location.Distance(playermidpoint) <= 5 &&
            //        player.HealthPercent <= healthPercent)
            //    {
            //        totalUnit = totalUnit + 1;
            //    }
            //}

            //return totalUnit;

            //return
            //    NearbyFriendlyPlayers.Where(
            //        unit =>
            //            unit.Location.Distance(WoWMathHelper.CalculatePointFrom(Me.Location,unitTarget.Location,5))
            //        unitCenter.Location.Distance(unit.Location) <= distance &&
            //        unit.HealthPercent <= healthPercent).Aggregate
            //        <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        #endregion

        #region CountFriendlyNearyNeedHeal

        private double CountFriendlyNearNeedHeal(WoWObject unitCenter, float distance, double healthPercent)
        {
            return
                NearbyFriendlyPlayers.Where(
                    unit =>
                    unitCenter.Location.Distance(unit.Location) <= distance &&
                    unit.HealthPercent <= healthPercent).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        #endregion

        #region FacingOverride

        private bool FacingOverride(WoWUnit unit)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (unit == null)
                {
                    return false;
                }

                if (SpecialUnit.Contains(unit.Entry))
                {
                    return true;
                }

                if (!IsOverrideModeOn && THSettings.Instance.AutoFace)
                {
                    return true;
                }

                if (TreeRoot.Current.Name == "Questing" ||
                    TreeRoot.Current.Name == "Grind Bot" ||
                    TreeRoot.Current.Name == "BGBuddy" ||
                    TreeRoot.Current.Name == "DungeonBuddy" ||
                    TreeRoot.Current.Name == "Mixed Mode")
                {
                    return true;
                }

                if (Me.IsFacing(unit))
                {
                    return true;
                }

                return false;
            }
        }

        #endregion

        #region GatherData

        //private readonly HashSet<int> _spellIDGather = new HashSet<int>
        //                                                   {
        //                                                       11196,
        //                                                   };

        //public List<string> DebuffandCastCollected = new List<string>();

        //private string GetCreateClassName(ulong createdbyguid)
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        WoWPlayer unitcreateaura = (from unit in ObjectManager.GetObjectsOfType<WoWPlayer>(true, true)
        //                                    where unit.Guid == createdbyguid
        //                                    select unit).FirstOrDefault();

        //        if (unitcreateaura != null && unitcreateaura.IsPlayer)
        //        {
        //            return unitcreateaura.Class.ToString();
        //        }
        //        if (unitcreateaura != null && unitcreateaura.IsPet)
        //        {
        //            return unitcreateaura.Class.ToString() + " (Pet)";
        //        }
        //    }
        //    return "";
        //}

        //public void GatherData()
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        List<WoWUnit> allUnit = ObjectManager.GetObjectsOfType<WoWUnit>(true, true);

        //        foreach (WoWUnit unit in allUnit)
        //        {
        //            foreach (var aura in unit.Debuffs)
        //            {
        //                if (!_spellIDGather.Contains(aura.Value.SpellId) &&
        //                    GetCreateClassName(aura.Value.CreatorGuid) != "")
        //                {
        //                    _spellIDGather.Add(aura.Value.SpellId);
        //                    //Logging.Write(GetCreateClassName(aura.Value.CreatorGuid) + "|" + "Debuff" + "|" + aura.Value.SpellId + "|" + aura.Value.Name + "|" + aura.Value.Spell.DispelType + "|" + aura.Value.Spell.Mechanic + "|" + aura.Value.Spell.BaseCooldown);
        //                    DebuffandCastCollected.Add(GetCreateClassName(aura.Value.CreatorGuid) + "|" + "Debuff" + "|" +
        //                                               aura.Value.SpellId + "|" + aura.Value.Name + "|" +
        //                                               aura.Value.Spell.DispelType + "|" + aura.Value.Spell.Mechanic +
        //                                               "|" + aura.Value.Spell.BaseCooldown);
        //                }
        //            }

        //            if (unit.IsCasting && !_spellIDGather.Contains(unit.CastingSpellId) &&
        //                GetCreateClassName(unit.Guid) != "")
        //            {
        //                _spellIDGather.Add(unit.CastingSpellId);
        //                //Logging.Write(unit.Class.ToString() + "|" + "Casting" + "|" + unit.CastingSpellId + "|" + unit.CastingSpell.Name + "|" +unit.CastingSpell.DispelType + "|" + unit.CastingSpell.Mechanic + "|" + unit.CastingSpell.BaseCooldown);
        //                DebuffandCastCollected.Add(unit.Class.ToString() + "|" + "Casting" + "|" + unit.CastingSpellId +
        //                                           "|" + unit.CastingSpell.Name + "|" + unit.CastingSpell.DispelType +
        //                                           "|" + unit.CastingSpell.Mechanic + "|" +
        //                                           unit.CastingSpell.BaseCooldown);
        //            }

        //            //foreach (var aura in unit.Buffs)
        //            //{
        //            //    if (!_spellIDGather.Contains(aura.Value.SpellId))
        //            //    {
        //            //        _spellIDGather.Add(aura.Value.SpellId);
        //            //        Logging.Write("Buff," + aura.Value.SpellId + "," + aura.Value.Name + "," + aura.Value.Spell.DispelType + "," + aura.Value.Spell.Mechanic + "," + aura.Value.Spell.BaseCooldown);
        //            //    }
        //            //}
        //        }
        //    }
        //}

        #endregion

        #region GCD

        private static DateTime _gcdReady;

        //private void UpdateGCDEvent(object sender, LuaEventArgs raw)
        //{
        //    var args = raw.Args;
        //    var player = Convert.ToString(args[0]);

        //    // Not me ... Im out!
        //    if (player != "player")
        //    {
        //        return;
        //    }
        //    var spellID = Convert.ToInt32(args[4]);
        //    var spellName = WoWSpell.FromId(spellID).Name;

        //}

        public static void UpdateGCD()
        {
            _gcdReady = DateTime.Now + GetSpellCooldown("Stance of the Fierce Tiger");
        }

        private static bool GCDL()
        {
            return DateTime.Now + TimeSpan.FromMilliseconds(MyLatency) < _gcdReady;
        }

        public static bool Casting()
        {
            if (Me.IsCasting &&
                Me.CurrentCastTimeLeft.TotalMilliseconds > MyLatency)
            {
                return true;
            }

            if (Me.IsChanneling && Me.ChanneledCastingSpellId == 115175) //Soothing Mist
            {
                return false;
            }

            if (Me.IsChanneling &&
                Me.ChanneledSpell.Id == 117952 &&
                Me.CurrentChannelTimeLeft.TotalMilliseconds > 4000) //Cracking Jade Ligntning
            {
                return true;
            }

            if (Me.IsChanneling &&
                Me.CurrentChannelTimeLeft.TotalMilliseconds > MyLatency &&
                Me.ChanneledSpell.Id != 117952) //Cracking Jade Ligntning
            {
                return true;
            }
            return false;
        }


        public static bool CastingorGCDL()
        {
            return Casting() || GCDL();
        }

        #endregion

        #region GetCurrentSpec

        public static string CurrentSpec;

        public static string GetCurrentSpec()
        {
            switch (Me.Specialization)
            {
                case WoWSpec.MonkBrewmaster:
                    CurrentSpec = "BrewMaster";
                    break;
                case WoWSpec.MonkMistweaver:
                    CurrentSpec = "MistWeaver";
                    break;
                default:
                    CurrentSpec = "WindWalker";
                    break;
            }
            return CurrentSpec;
        }

        #endregion

        #region GetAsyncKeyState

        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        #endregion

        #region GetSpellCooldown

        //public static TimeSpan GetSpellCooldown(string spell)
        //{
        //    SpellFindResults results;
        //    if (SpellManager.FindSpell(spell, out results))
        //    {
        //        return results.Override != null ? results.Override.CooldownTimeLeft : results.Original.CooldownTimeLeft;
        //    }

        //    return TimeSpan.MaxValue;
        //}

        public static TimeSpan GetSpellCooldown(string spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                if (results.Override != null)
                {
                    return results.Override.CooldownTimeLeft;
                }
                return results.Original.CooldownTimeLeft;
            }


            return TimeSpan.MaxValue;
        }

        #endregion

        #region GetUnitAuras

        //public double AuraCCDuration;
        //public double AuraCCDurationMax;
        //public WoWAura AuraCC;

        //public double AuraCCBreakonDamageDuration;
        //public double AuraCCBreakonDamageDurationMax;
        //public WoWAura AuraCCBreakonDamage;

        //public double AuraDisarmDuration;
        //public double AuraDisarmDurationMax;
        //public WoWAura AuraDisarm;

        //public double AuraImmuneDuration;
        //public double AuraImmuneDurationMax;
        //public WoWAura AuraImmune;

        //public double AuraImmunePhysicDuration;
        //public double AuraImmunePhysicDurationMax;
        //public WoWAura AuraImmunePhysic;

        //public double AuraImmuneSpellDuration;
        //public double AuraImmuneSpellDurationMax;
        //public WoWAura AuraImmuneSpell;

        //public double AuraRootDuration;
        //public double AuraRootDurationMax;
        //public WoWAura AuraRoot;

        //public double AuraSilenceDuration;
        //public double AuraSilenceDurationMax;
        //public WoWAura AuraSilence;

        //public double AuraSnareDuration;
        //public double AuraSnareDurationMax;
        //public WoWAura AuraSnare;

        //public WoWAura AuraCleanseDoNot;
        //public WoWAura AuraHealDoNot;
        //public int NumberofDebuff;

        //public bool GetUnitAuras(WoWUnit u)
        //{
        //    if (u == null || !u.IsValid || !u.IsAlive)
        //        return false;

        //    AuraCC = null;
        //    AuraCCDuration = 0;
        //    AuraCCDurationMax = 0;

        //    AuraCCBreakonDamage = null;
        //    AuraCCBreakonDamageDuration = 0;
        //    AuraCCBreakonDamageDurationMax = 0;

        //    AuraDisarm = null;
        //    AuraDisarmDuration = 0;
        //    AuraDisarmDurationMax = 0;

        //    AuraImmune = null;
        //    AuraImmuneDuration = 0;
        //    AuraImmuneDurationMax = 0;

        //    AuraImmuneSpell = null;
        //    AuraImmuneSpellDuration = 0;
        //    AuraImmuneSpellDurationMax = 0;

        //    AuraImmunePhysic = null;
        //    AuraImmunePhysicDuration = 0;
        //    AuraImmunePhysicDurationMax = 0;

        //    AuraRoot = null;
        //    AuraRootDuration = 0;
        //    AuraRootDurationMax = 0;

        //    AuraSilence = null;
        //    AuraSilenceDuration = 0;
        //    AuraSilenceDurationMax = 0;

        //    AuraSnare = null;
        //    AuraSnareDuration = 0;
        //    AuraSnareDurationMax = 0;

        //    NumberofDebuff = 0;
        //    AuraCleanseDoNot = null;
        //    AuraHealDoNot = null;

        //    foreach (var aura in u.GetAllAuras())
        //    {
        //        //Count Number of Debuff
        //        if (aura.IsHarmful &&
        //            (aura.Spell.DispelType == WoWDispelType.Disease ||
        //             aura.Spell.DispelType == WoWDispelType.Magic ||
        //             aura.Spell.DispelType == WoWDispelType.Poison))
        //        {
        //            NumberofDebuff = NumberofDebuff + 1;
        //        }

        //        //Find out if AuraCleanseDoNot exits
        //        if (ListCleanseDoNot.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraCleanseDoNot = aura.;
        //        }

        //        //Find out if AuraHealDoNot exits
        //        if (ListHealDoNot.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraHealDoNot = aura.;
        //        }

        //        if (ListCC.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraCCDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraCCDuration > AuraCCDurationMax)
        //            {
        //                AuraCC = aura.;
        //                AuraCCDurationMax = AuraCCDuration;
        //            }
        //        }

        //        if (ListCCBreakonDamage.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraCCBreakonDamageDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraCCBreakonDamageDuration > AuraCCBreakonDamageDurationMax)
        //            {
        //                AuraCCBreakonDamage = aura.;
        //                AuraCCBreakonDamageDurationMax = AuraCCBreakonDamageDuration;
        //            }
        //        }

        //        if (ListDisarm.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraDisarmDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraDisarmDuration > AuraDisarmDurationMax)
        //            {
        //                AuraDisarm = aura.;
        //                AuraDisarmDurationMax = AuraDisarmDuration;
        //            }
        //        }

        //        if (ListImmune.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraImmuneDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraImmuneDuration > AuraImmuneDurationMax)
        //            {
        //                AuraImmune = aura.;
        //                AuraImmuneDurationMax = AuraImmuneDuration;
        //            }
        //        }

        //        if (ListImmuneSpell.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraImmuneSpellDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraImmuneSpellDuration > AuraImmuneSpellDurationMax)
        //            {
        //                AuraImmuneSpell = aura.;
        //                AuraImmuneSpellDurationMax = AuraImmuneSpellDuration;
        //            }
        //        }

        //        if (ListImmunePhysic.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraImmunePhysicDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraImmunePhysicDuration > AuraImmunePhysicDurationMax)
        //            {
        //                AuraImmunePhysic = aura.;
        //                AuraImmunePhysicDurationMax = AuraImmunePhysicDuration;
        //            }
        //        }

        //        if (ListRoot.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraRootDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraRootDuration > AuraRootDurationMax)
        //            {
        //                AuraRoot = aura.;
        //                AuraRootDurationMax = AuraRootDuration;
        //            }
        //        }

        //        if (ListSilence.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraSilenceDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraSilenceDuration > AuraSilenceDurationMax)
        //            {
        //                AuraSilence = aura.;
        //                AuraSilenceDurationMax = AuraSilenceDuration;
        //            }
        //        }

        //        if (ListSnare.Contains("[" + aura.SpellId + "]"))
        //        {
        //            AuraSnareDuration = aura.TimeLeft.TotalMilliseconds;
        //            if (AuraSnareDuration > AuraSnareDurationMax)
        //            {
        //                AuraSnare = aura.;
        //                AuraSnareDurationMax = AuraSnareDuration;
        //            }
        //        }
        //    }
        //    return true;
        //}

        #endregion

        #region GetAllMyAuras

        public DateTime LastGetAllMyAuras = DateTime.Now;

        public void DumpAuras()
        {
            if (LastGetAllMyAuras.AddSeconds(10) < DateTime.Now)
            {
                int i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (WoWAura aura in Me.GetAllAuras())
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.GetAllAuras Name: " + aura.Name + " - SpellId: " + aura.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (var aura in Me.Auras)
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.Auras - Name: " + aura.Value.Name + " - SpellId: " + aura.Value.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (var aura in Me.ActiveAuras)
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.ActiveAuras - Name: " + aura.Value.Name + " - SpellId: " +
                                  aura.Value.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (var aura in Me.PassiveAuras)
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.PassiveAuras - Name: " + aura.Value.Name + " - SpellId: " +
                                  aura.Value.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                LastGetAllMyAuras = DateTime.Now;
            }
        }

        #endregion

        #region GetDistance

        private static float GetDistance(WoWUnit target)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (target != null)
                {
                    return (float)Math.Max(0f, target.Distance2D - target.BoundingRadius);
                }
                return 0;
            }
        }

        #endregion

        #region GetPlayerGotMyHandofSacrifice

        public WoWUnit PlayerGotMyHandofSacrifice;

        //private bool GetPlayerGotMyHandofSacrifice()
        //{
        //    PlayerGotMyHandofSacrifice = null;
        //    PlayerGotMyHandofSacrifice = (from unit in NearbyUnFriendlyPlayers
        //                                  where MyAura("Hand of Sacrifice", unit)
        //                                  select unit).FirstOrDefault();
        //    return PlayerGotMyHandofSacrifice != null;
        //}

        #endregion

        #region GetUnitDispellerAround

        public WoWUnit UnitDispellerAround;

        private bool GetUnitDispellerAround()
        {
            UnitDispellerAround = null;
            UnitDispellerAround = (from unit in NearbyUnFriendlyUnits
                                   orderby unit.Distance ascending
                                   where unit.IsPlayer
                                   where
                                       unit.Class == WoWClass.Hunter || unit.Class == WoWClass.Mage ||
                                       unit.Class == WoWClass.Priest || unit.Class == WoWClass.Shaman
                                   where AttackableValid(unit)
                                   select unit).FirstOrDefault();

            return UnitDispellerAround != null;
        }

        #endregion

        #region GetUnitLowThreat

        private WoWUnit _unitLowThreat;

        private bool GetUnitLowThreat()
        {
            _unitLowThreat = null;
            _unitLowThreat = (from unit in NearbyUnFriendlyUnits
                              orderby unit.ThreatInfo.RawPercent ascending
                              where Me.Combat
                              where Me.CurrentMap.IsDungeon || Me.CurrentMap.IsRaid
                              where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                                     unit.IsTargetingMeOrPet)
                              where unit.IsWithinMeleeRange
                              select unit).FirstOrDefault();
            return _unitLowThreat != null;
        }

        #endregion

        #region GetUnitNear

        public WoWUnit UnitNear;

        private bool GetUnitNear()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                UnitNear = null;
                UnitNear = (from unit in NearbyUnFriendlyUnits
                            orderby unit.Distance ascending
                            where Me.Combat
                            where Me.CurrentMap.IsDungeon || Me.CurrentMap.IsRaid
                            where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                                   unit.IsTargetingMeOrPet)
                            select unit).FirstOrDefault();
                return UnitNear != null;
            }
        }

        #endregion

        #region Healable

        private bool Healable(WoWUnit u)
        {
            if (ValidUnit(u) && u.Distance < 40 && !IsEnemy(u) && !DebuffDoNotHeal(u) && u.InLineOfSpellSight)
            {
                return true;
            }
            return false;
        }

        //prevent double ValidUnit Check
        private bool HealableValid(WoWUnit u)
        {
            if (u.Distance < 40 && !IsEnemy(u) && !DebuffDoNotHeal(u) && u.InLineOfSpellSight)
            {
                return true;
            }
            return false;
        }

        //public bool Healable60(WoWUnit u)
        //{
        //    if (ValidUnit(u) && u.Distance < 60 && !IsEnemy(u) && !DebuffDoNotHeal(u) && u.InLineOfSpellSight)
        //    {
        //        return true;
        //    }
        //    return false;
        //}

        //prevent double ValidUnit Check
        //public bool Healable60Valid(WoWUnit u)
        //{
        //    if (u.Distance < 60 && !IsEnemy(u) && !DebuffDoNotHeal(u) && u.InLineOfSpellSight)
        //    {
        //        return true;
        //    }
        //    return false;
        //}

        #endregion

        #region Hold

        //public static string MyCastingSpells =
        //    "[Divine Light] [Flash of Light] [Holy Light] [Divine Plea] [Holy Radiance] [Holy Shock] [Light of Dawn] [Word of Glory] [Denounce] [Repentance]";

        public Composite Hold()
        {
            return
                new Decorator(
                    ret =>
                    Me.HasAura("Drink") && Me.Specialization == WoWSpec.MonkMistweaver &&
                    Me.ManaPercent < THSettings.Instance.DoNotHealAbove ||
                    Me.HasAura("Food") && Me.CurrentHealth < THSettings.Instance.DoNotHealAbove ||
                    !Me.IsAlive || InputLasting > DateTime.Now,
                    new Action(delegate
                                   {
                                       Logging.Write("Hold");
                                       return RunStatus.Success;
                                   })
                    );
        }

        #endregion

        #region IndexToKeys

        public Keys KeyTwo;

        private Keys IndexToKeys(int index)
        {
            switch (index)
            {
                case 1:
                    return Keys.A;
                case 2:
                    return Keys.B;
                case 3:
                    return Keys.C;
                case 4:
                    return Keys.D;
                case 5:
                    return Keys.E;
                case 6:
                    return Keys.F;
                case 7:
                    return Keys.G;
                case 8:
                    return Keys.H;
                case 9:
                    return Keys.I;
                case 10:
                    return Keys.J;
                case 11:
                    return Keys.K;
                case 12:
                    return Keys.L;
                case 13:
                    return Keys.M;
                case 14:
                    return Keys.N;
                case 15:
                    return Keys.O;
                case 16:
                    return Keys.P;
                case 17:
                    return Keys.Q;
                case 18:
                    return Keys.R;
                case 19:
                    return Keys.S;
                case 20:
                    return Keys.T;
                case 21:
                    return Keys.U;
                case 22:
                    return Keys.V;
                case 23:
                    return Keys.W;
                case 24:
                    return Keys.X;
                case 25:
                    return Keys.Y;
                case 26:
                    return Keys.Z;
                case 27:
                    return Keys.NumPad1;
                case 28:
                    return Keys.NumPad2;
                case 29:
                    return Keys.NumPad3;
                case 30:
                    return Keys.NumPad4;
                case 31:
                    return Keys.NumPad5;
                case 32:
                    return Keys.NumPad6;
                case 33:
                    return Keys.NumPad7;
                case 34:
                    return Keys.NumPad8;
                case 35:
                    return Keys.NumPad9;
                case 36:
                    return Keys.NumPad0;
                case 37:
                    return Keys.Up;
                case 38:
                    return Keys.Down;
                case 39:
                    return Keys.Left;
                case 40:
                    return Keys.Right;
            }
            return Keys.None;
        }

        #endregion

        #region InputBlockCheck

        public DateTime InputLasting;

        [DllImport("user32.dll")]
        private static extern bool BlockInput(bool block);

        //public Stopwatch InputBlockSafeStopWatch = new Stopwatch();

        public void InputBlockCheck()
        {
            if (InputLasting > DateTime.Now)
            {
                SendKeys.Flush();
                BlockInput(true);
            }

            if (InputLasting <= DateTime.Now)
            {
                SendKeys.Flush();
                BlockInput(false);
            }
        }

        public void InputBlockUse(bool switcher, string spellName)
        {
            if (THSettings.Instance.InputBlockMode &&
                switcher && !IsOverrideModeOn && spellName == "Fists of Fury" && THSettings.Instance.BlockInputFoF)
            //(spellName == "Roll" && THSettings.Instance.BlockInputRoll ||
            // spellName == "Flying Serpent Kick" && THSettings.Instance.BlockInputFSK ||
            // spellName == "Fists of Fury" && THSettings.Instance.BlockInputFoF))
            {
                InputLasting = DateTime.Now + TimeSpan.FromMilliseconds(THSettings.Instance.BlockInputDelay);
                BlockInput(true);
            }
        }

        #endregion

        #region InterruptCast

        public double InterruptCastNoChannel(WoWUnit target)
        {
            if (target == null)
            {
                return 0;
            }
            double timeLeft = 0;

            if (target.IsCasting && (target.CastingSpellId == 30451 || //Arcane Blast 
                                     target.CastingSpellId == 33786 || //Cyclone 
                                     target.CastingSpellId == 421 || //Chain Lightning 
                                     target.CastingSpellId == 50796 || //Chaos Bolt 
                                     target.CastingSpellId == 339 || //Entangling Roots 
                                     target.CastingSpellId == 5782 || //Fear 
                                     target.CastingSpellId == 133 || //Fireball 
                                     target.CastingSpellId == 116 || //Frostbolt 
                                     target.CastingSpellId == 44614 || //Frostfire Bolt 
                                     target.CastingSpellId == 71521 || //Hand of Gul'dan 
                                     target.CastingSpellId == 48181 || //Haunt 
                                     target.CastingSpellId == 51514 || //Hex 
                                     target.CastingSpellId == 14914 || //Holy Fire 
                                     target.CastingSpellId == 348 || //Immolate 
                                     target.CastingSpellId == 29722 || //Incinerate 
                                     target.CastingSpellId == 51505 || //Lava Burst 
                                     target.CastingSpellId == 403 || //Lightning Bolt 
                                     target.CastingSpellId == 8129 || //Mana Burn 
                                     target.CastingSpellId == 8092 || //Mind Blast 
                                     target.CastingSpellId == 605 || //Mind Control 
                                     target.CastingSpellId == 73510 || //Mind Spike 
                                     target.CastingSpellId == 118 || //Polymorph 
                                     target.CastingSpellId == 28272 || //Polymorph 
                                     target.CastingSpellId == 61721 || //Polymorph 
                                     target.CastingSpellId == 61305 || //Polymorph 
                                     target.CastingSpellId == 61780 || //Polymorph 
                                     target.CastingSpellId == 28271 || //Polymorph 
                                     target.CastingSpellId == 11366 || //Pyroblast 
                                     target.CastingSpellId == 2948 || //Scorch 
                                     target.CastingSpellId == 5676 || //Searing Pain 
                                     target.CastingSpellId == 27243 || //Seed of Corruption 
                                     target.CastingSpellId == 686 || //Shadow Bolt 
                                     target.CastingSpellId == 585 || //Smite 
                                     target.CastingSpellId == 6353 || //Soul Fire 
                                     target.CastingSpellId == 2912 || //Starfire 
                                     target.CastingSpellId == 78674 || //Starsurge 
                                     target.CastingSpellId == 30108 || //Unstable Affliction 
                                     target.CastingSpellId == 5176 || //Wrath 
                                     target.CastingSpellId == 34914)) //Vampiric Touch
            {
                timeLeft = target.CurrentCastTimeLeft.TotalMilliseconds;
            }
            //if (target != null && target.IsCasting && ListCastSpellInterrupt.Contains("[" + target.CastingSpellId + "]"))
            //{
            //    timeLeft = target.CurrentCastTimeLeft.TotalMilliseconds;
            //}
            return timeLeft;
        }

        //public double OffensiveCastNoChannel(WoWUnit target)
        //{
        //    double timeLeft = 0;

        //    const string spellNoChanneled = "[30451]=Arcane Blast [33786]=Cyclone [421]=Chain Lightning [50796]=Chaos Bolt [339]Entangling Roots [5782]=Fear [133]=Fireball [116]=Frostbolt [44614]=Frostfire Bolt [71521]=Hand of Gul'dan [48181]=Haunt [51514]=Hex [14914]=Holy Fire [348]=Immolate [29722]=Incinerate [51505]=Lava Burst [403=Lightning Bolt [8129]=Mana Burn [8092]=Mind Blast [605]=Mind Control [73510]=Mind Spike [118][28272][61721][61305][61780][28271]=Polymorph [11366]=Pyroblast [2948=]Scorch [5676]=Searing Pain [27243]=Seed of Corruption [686]=Shadow Bolt [585]=Smite [6353]=Soul Fire [2912]=Starfire [78674]=Starsurge [30108]=Unstable Affliction [5176]=Wrath [34914]=Vampiric Touch";

        //    if (target != null && target.IsCasting && spellNoChanneled.Contains("[" + target.CastingSpellId + "]"))
        //    {
        //        timeLeft = target.CurrentCastTimeLeft.TotalMilliseconds;
        //    }
        //    return timeLeft;
        //}

        public double InterruptCastChannel(WoWUnit target)
        {
            if (target == null)
            {
                return 0;
            }
            double timeLeft = 0;

            if (target.IsChanneling && (target.ChanneledCastingSpellId == 689 || //Drain Life  
                                        target.ChanneledCastingSpellId == 1120 || //Drain Soul  
                                        target.ChanneledCastingSpellId == 5143 || //Arcane Missiles  
                                        target.ChanneledCastingSpellId == 15407 || //Mind Flay  
                                        target.ChanneledCastingSpellId == 47540 || // Penance
                                        target.ChanneledCastingSpellId == 740 || //tranquility
                                        target.ChanneledCastingSpellId == 89420)) //Drain Life
            {
                timeLeft = target.CurrentChannelTimeLeft.TotalMilliseconds;
            }

            //if (target != null && target.IsCasting &&
            //    ListChannelSpellsInterrupt.Contains("[" + target.CastingSpellId + "]"))
            //{
            //    timeLeft = 500;
            //}
            return timeLeft;
        }

        //public double OffensiveCastChannel(WoWUnit target)
        //{
        //    double timeLeft = 0;
        //    const string spellChanneled = "[689]=Drain Life [879]=Exorcism [1120]=Drain Soul [5143]=Arcane Missiles [15407]=Mind Flay [89420]=Drain Life";

        //    if (target != null && target.IsCasting && spellChanneled.Contains("_" + target.CastingSpellId + "_"))
        //    {
        //        timeLeft = 111;
        //    }
        //    return timeLeft;
        //}

        #endregion

        #region IsHealing

        private static bool IsHealing()
        {
            return Me.IsCasting &&
                   (Me.CastingSpell.Name == "Flash of Light" || Me.CastingSpell.Name == "Divine Light" ||
                    Me.CastingSpell.Name == "Holy Light" || Me.CastingSpell.Name == "Holy Radiance");
        }

        #endregion

        #region IsAttacking

        //private static bool IsAttacking()
        //{
        //    return Me.IsCasting && Me.CastingSpell.Name == "Denounce";
        //}

        #endregion

        #region IsGroupHealingOn

        private bool _groupHealingOn;

        public bool IsGroupHealingOn()
        {
            if (!SpellManager.HasSpell("Holy Insight"))
            {
                //Logging.Write("----------------------------------");
                //Logging.Write("Group Healing Mode Off");
                //Logging.Write("Only Activated in Holy Specialization");
                //Logging.Write("----------------------------------");
                _groupHealingOn = false;
                return false;
            }

            if (THSettings.Instance.Group1 &&
                THSettings.Instance.Group2 &&
                THSettings.Instance.Group3 &&
                THSettings.Instance.Group4 &&
                THSettings.Instance.Group5 &&
                THSettings.Instance.Group6 &&
                THSettings.Instance.Group7 &&
                THSettings.Instance.Group8
                )
            {
                //Logging.Write("----------------------------------");
                //Logging.Write("Group Healing Mode Off");
                //Logging.Write("All Group Selected");
                //Logging.Write("----------------------------------");
                _groupHealingOn = false;
                return false;
            }

            if (!THSettings.Instance.Group1 &&
                !THSettings.Instance.Group2 &&
                !THSettings.Instance.Group3 &&
                !THSettings.Instance.Group4 &&
                !THSettings.Instance.Group5 &&
                !THSettings.Instance.Group6 &&
                !THSettings.Instance.Group7 &&
                !THSettings.Instance.Group8
                )
            {
                //Logging.Write("----------------------------------");
                //Logging.Write("Selective Group Healing Mode Off");
                //Logging.Write("Not a Single Group Selected");
                //Logging.Write("----------------------------------");
                _groupHealingOn = false;
                return false;
            }

            if (!Me.IsInMyRaid)
            {
                //Logging.Write("----------------------------------");
                //Logging.Write("Selective Group Healing Mode Off");
                //Logging.Write("You are not in Raid");
                //Logging.Write("----------------------------------");
                _groupHealingOn = false;
                return false;
            }

            if (Me.CurrentMap.IsBattleground)
            {
                //Logging.Write("----------------------------------");
                //Logging.Write("Selective Group Healing Mode Off");
                //Logging.Write("You are in Battleground");
                //Logging.Write("----------------------------------");

                //Logging.Write("Me.CurrentMap: " + Me.CurrentMap);
                //Logging.Write("Me.CurrentMap.IsArena: " + Me.CurrentMap.IsArena);
                //Logging.Write("Me.CurrentMap.IsBattleground: " + Me.CurrentMap.IsBattleground);
                //Logging.Write("Me.CurrentMap.IsDungeon: " + Me.CurrentMap.IsDungeon);
                //Logging.Write("Me.CurrentMap.IsRaid: " + Me.CurrentMap.IsRaid);
                //Logging.Write("Me.CurrentMap.IsScenario: " + Me.CurrentMap.IsScenario);
                _groupHealingOn = false;
                return false;
            }

            Logging.Write("----------------------------------");
            Logging.Write("Selective Group Healing Mode On");
            Logging.Write("----------------------------------");
            _groupHealingOn = true;
            return true;
        }

        #endregion

        #region IsEnemy

        public WoWUnit MyPartyorRaidUnit;

        public bool IsMyPartyRaidMember(WoWUnit u)
        {
            if (u == null || !u.IsValid)
            {
                return false;
            }

            if (_groupHealingOn && !GroupHealingMembers.Contains(u))
            {
                return false;
            }

            if (!u.IsPlayer)
            {
                if (Me.PartyMembers.Contains(u.CreatedByUnit) || Me.RaidMembers.Contains(u.CreatedByUnit))
                {
                    return true;
                }
            }
            else
            {
                if (Me.PartyMembers.Contains(u) || Me.RaidMembers.Contains(u))
                {
                    return true;
                }
            }

            return false;
        }

        //private bool UnitIsInMyPartyOrRaid(WoWUnit target)
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        MyPartyorRaidUnit = (from unit in ObjectManager.GetObjectsOfType<WoWPlayer>(true, true)
        //                             where unit.IsInMyPartyOrRaid
        //                             where unit.Guid == target.Guid || unit.Guid == target.CreatedByUnitGuid
        //                             select unit).FirstOrDefault();
        //    }
        //    return MyPartyorRaidUnit != null;
        //}

        public bool IsEnemy(WoWUnit target)
        {
            if (target == null)
            {
                return false;
            }

            if (target.Entry == 62442 && !target.Attackable) //tsulong
            {
                return false;
            }

            if (target.HasAura(122784) || //Reshape Life
                target.HasAura(122740)) //Convert
            {
                return true;
            }

            if (IsMyPartyRaidMember(target))
            {
                return false;
            }

            if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
            {
                return true;
            }

            if (!target.IsFriendly || target.Name.Contains("Dummy") && Me.Combat && Me.IsFacing(target))
            {
                return true;
            }
            return false;
        }

        #endregion

        #region IsMeorFocus

        public bool IsMeorFocus(WoWUnit target)
        {
            if (target == Me ||
                target == Me.FocusedUnit && ValidUnit(Me.FocusedUnit) && !IsEnemy(Me.FocusedUnit) ||
                target == Me.CurrentTarget && ValidUnit(Me.CurrentTarget) && !IsEnemy(Me.CurrentTarget) ||
                Me.CurrentMap.IsArena)
            {
                return true;
            }
            return false;
        }

        #endregion

        #region MeIsTank

        public static bool MeIsTank
        {
            get
            {
                //return (StyxWoW.Me.Role & WoWPartyMember.GroupRole.Tank) != 0 ||
                //        Tanks.All(t => !t.IsAlive) && StyxWoW.Me.HasAura("Bear Form");
                return (StyxWoW.Me.Role & WoWPartyMember.GroupRole.Tank) != 0;
            }
        }

        #endregion

        #region MyAura

        public bool MyAura(string auraName, WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return false;

                bool aura = u.GetAllAuras().Any(a => a.Name == auraName && a.CreatorGuid == Me.Guid);

                return aura;
                //return u.ActiveAuras.Any(a => a.Value.Name == auraName && a.Value.CreatorGuid == Me.Guid);
            }
        }


        public bool MyAura(int auraID, WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return false;

                bool aura = u.GetAllAuras().Any(a => a.SpellId == auraID && a.CreatorGuid == Me.Guid);

                return aura;

                //return u.ActiveAuras.Any(a => a.Value.SpellId == auraID && a.Value.CreatorGuid == Me.Guid);
            }
        }

        #endregion

        #region MyAuraTimeLeft

        public double MyAuraTimeLeft(string auraName, WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        public double MyAuraTimeLeft(int auraID, WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region LogTest

        //private Composite LogTest(string message)
        //{
        //    return new Action(delegate
        //                          {
        //                              Logging.Write(LogLevel.Diagnostic, "LogTest: " + message);
        //                              return RunStatus.Failure;
        //                          });
        //}

        #endregion

        #region UnitAuraTimeLeft

        public double UnitAuraTimeLeft(string auraName, WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        public double UnitAuraTimeLeft(int auraID, WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region MyAuraStackCount

        public double MyAuraStackCount(string auraName, WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
        }

        public double MyAuraStackCount(int auraID, WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
        }

        #endregion

        #region SafelyFacingTarget

        public void SafelyFacingTarget(WoWUnit unit)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (THSettings.Instance.AutoFace && !IsOverrideModeOn && unit != null)
                {
                    unit.Face();
                }

                //if (unit == null || Me.Mounted ||
                //    SpecialUnit.Contains(unit.Entry) ||
                //    Blacklist.Contains(unit.Guid, BlacklistFlags.All))
                //{
                //    return;
                //}

                //if (THSettings.Instance.AutoFace && !IsOverrideModeOn && !Me.IsSafelyFacing(unit))
                //{
                //    unit.Face();
                //    WoWMovement.ConstantFace(unit.Guid);
                //}
            }
        }

        #endregion

        #region SetAutoAttack

        public Composite SetAutoAttack()
        {
            return new Action(delegate
                                  {
                                      if (Me.Combat && Me.IsAutoAttacking && Me.CurrentTarget != null &&
                                          Me.CurrentTarget.IsValid &&
                                          (Me.CurrentTarget.HasAura("Water Shield") && Me.CurrentTarget.IsPlayer &&
                                           Me.IsFFAPvPFlagged ||
                                           DebuffCCBreakonDamage(Me.CurrentTarget) || Invulnerable(Me.CurrentTarget) ||
                                           !THSettings.Instance.AutoAttack))
                                      {
                                          //Logging.Write("Stop Attack");
                                          Lua.DoString("RunMacroText('/stopattack');");
                                      }

                                      //Disable this, it conflic with the targeting system
                                      //if (Me.Combat && THSettings.Instance.SAutoAttack && !Me.IsAutoAttacking &&
                                      //    //Me.CurrentTarget != null && Me.CurrentTarget.IsValid &&
                                      //    Attackable(Me.CurrentTarget,5))
                                      //{
                                      //    //Logging.Write("Start Attack");
                                      //    Lua.DoString("RunMacroText('/startattack');");
                                      //}
                                      return RunStatus.Failure;
                                  });
        }

        #endregion

        #region SpellType

        private static readonly HashSet<string> AttackSpells = new HashSet<string>
                                                                   {
                                                                       "Blackout Kick",
                                                                       "Breath of Fire",
                                                                       "Crackling Jade Lightning",
                                                                       "Dizzying Haze",
                                                                       "Energizing Brew",
                                                                       "Flying Serpent Kick",
                                                                       "Invoke Xuen, the White Tiger",
                                                                       "Jab",
                                                                       "Keg Smash",
                                                                       "Leer of the Ox",
                                                                       "Path of Blossoms",
                                                                       "Provoke",
                                                                       "Rising Sun Kick",
                                                                       "Roll",
                                                                       "Spinning Crane Kick",
                                                                       "Spinning Fire Blossom",
                                                                       "Tiger Palm",
                                                                       "Tigereye Brew",
                                                                       "Touch of Death",
                                                                   };

        private static readonly HashSet<string> DefendSpells = new HashSet<string>
                                                                   {
                                                                       "Avert Harm",
                                                                       "Dampen Harm",
                                                                       "Diffuse Magic",
                                                                       "Elusive Brew",
                                                                       "Enveloping Mist",
                                                                       "Fortifying Brew",
                                                                       "Guard",
                                                                       "Healing Sphere",
                                                                       "Mana Tea",
                                                                       "Purifying Brew",
                                                                       "Renewing Mist",
                                                                       "Resuscitate",
                                                                       "Soothing Mist",
                                                                       "Summon Black Ox Statue",
                                                                       "Summon Jade Serpent Statue",
                                                                       "Surging Mist",
                                                                       "Transcendence",
                                                                       "Transcendence: Transfer",
                                                                       "Uplift",
                                                                       "Zen Meditation",
                                                                       "Zen Sphere",
                                                                   };

        private static readonly HashSet<string> SpecialSpells = new HashSet<string>
                                                                    {
                                                                        "Charging Ox Wave",
                                                                        "Clash",
                                                                        "Detox",
                                                                        "Disable",
                                                                        "Fists of Fury",
                                                                        "Grapple Weapon",
                                                                        "Leg Sweep",
                                                                        "Paralysis",
                                                                        "Spear Hand Strike",
                                                                    };

        #endregion

        #region TalentSort

        public byte TalentSort(WoWUnit target)
        {
            if (target == null)
            {
                return 0;
            }

            if (!target.IsPlayer)
            {
                return 0;
            }

            if (target.Class == WoWClass.DeathKnight)
            {
                return 1;
            }

            if (target.Class == WoWClass.Druid)
            {
                if (target.Buffs.ContainsKey("Moonkin Form"))
                    return 3;
                if ((target.Buffs.ContainsKey("Leader of the Pack") &&
                     target.Buffs["Leader of the Pack"].CreatorGuid == target.Guid) ||
                    target.MaxMana < target.MaxHealth / 2)
                    return 1;
                return 4;
            }

            if (target.Class == WoWClass.Hunter)
            {
                return 2;
            }

            if (target.Class == WoWClass.Mage)
            {
                return 3;
            }

            if (target.Class == WoWClass.Monk)
            {
                if (target.MaxMana >= target.MaxHealth / 2)
                    return 4;
                return 1;
            }

            if (target.Class == WoWClass.Paladin)
            {
                if (target.MaxMana > target.MaxMana / 2)
                    return 4;
                return 1;
            }

            if (target.Class == WoWClass.Priest)
            {
                if (target.HasAura("Shadowform"))
                    return 3;
                return 4;
            }

            if (target.Class == WoWClass.Rogue)
            {
                return 1;
            }

            if (target.Class == WoWClass.Shaman)
            {
                if (target.MaxMana < target.MaxHealth / 2)
                    return 1;
                if (target.Buffs.ContainsKey("Elemental Oath") &&
                    target.Buffs["Elemental Oath"].CreatorGuid == target.Guid)
                    return 3;
                return 4;
            }

            if (target.Class == WoWClass.Warlock)
            {
                return 3;
            }

            if (target.Class == WoWClass.Warrior)
            {
                return 1;
            }

            return 0;
        }

        public byte TalentSortSimple(WoWUnit target)
        {
            byte sortSimple = TalentSort(target);

            if (sortSimple == 4)
            {
                return 4;
            }

            if (sortSimple < 4 && sortSimple > 0)
            {
                return 1;
            }

            return 0;
        }

        #endregion

        #region UpdateStatusEvent

        public void UpdateStatusEvent(object sender, LuaEventArgs args)
        {
            THSettings.Instance.UpdateStatus = true;
        }

        #endregion

        #region OnBotStartedEvent

        private bool RollRemoveSnare;

        private void OnBotStartedEvent(object o)
        {
            if (Me.Inventory.Equipped.Hands != null &&
                Me.Inventory.Equipped.Hands.Name.Contains("Gladiator's Ironskin Gloves"))
            {
                RollRemoveSnare = true;
            }
            Logging.Write("----------------------------------");
            Logging.Write("Update Status on Bot Start");
            Logging.Write("----------------------------------");
            THSettings.Instance.Pause = false;
            THSettings.Instance.UpdateStatus = true;
        }

        #endregion

        #region SpecialUnit

        private static readonly HashSet<uint> SpecialUnit = new HashSet<uint>
                                                                {
                                                                    60410, //Elegon
                                                                    60776, //Empyreal Focus
                                                                    60793, //Celestial Protector
                                                                    60913, //Energy Charge
                                                                    60143, //garajal-the-spiritbinder
                                                                    60412, //Empyreal Focus
                                                                };

        #endregion

        #region UpdateCurrentMap

        //public string CurrentMap;

        //private void UpdateCurrentMapEvent(BotEvents.Player.MapChangedEventArgs args)
        //{
        //    THSettings.Instance.UpdateStatus = true;
        //}

        //public void UpdateCurrentMap()
        //{
        //    if (Me.CurrentMap.IsArena)
        //    {
        //        CurrentMap = "Arena";
        //    }
        //    else if (Me.CurrentMap.IsBattleground && Me.IsFFAPvPFlagged)
        //    {
        //        CurrentMap = "Rated Battleground";
        //    }
        //    else if (Me.CurrentMap.IsBattleground)
        //    {
        //        CurrentMap = "Battleground";
        //    }
        //    else if (Me.CurrentMap.IsDungeon)
        //    {
        //        CurrentMap = "Dungeon";
        //    }
        //    else if (Me.CurrentMap.IsRaid)
        //    {
        //        CurrentMap = "Raid";
        //    }
        //    else
        //    {
        //        CurrentMap = "World";
        //    }

        //    Logging.Write("----------------------------------");
        //    Logging.Write("CurrentMap: " + CurrentMap);
        //    Logging.Write("----------------------------------");
        //}

        #endregion

        #region UpdateGroupHealingMembers

        public void UpdateGroupChangeEvent(object sender, LuaEventArgs args)
        {
            if (IsGroupHealingOn())
            {
                Logging.Write("Update Selective Group Healing on Group Member Change");
                THSettings.Instance.UpdateStatus = true;
            }
        }

        public List<WoWPlayer> GroupHealingMembers = new List<WoWPlayer>();

        public void UpdateGroupHealingMembers()
        {
            GroupHealingMembers.Clear();
            //Logging.Write("Debug " + GroupHealingMembers.Count() + " Members");

            if (IsGroupHealingOn())
            {
                foreach (var woWPartyMember in GroupMembers)
                {
                    if (woWPartyMember.ToPlayer() != null)
                    {
                        if (THSettings.Instance.Group1 && woWPartyMember.GroupNumber == 0 ||
                            THSettings.Instance.Group2 && woWPartyMember.GroupNumber == 1 ||
                            THSettings.Instance.Group3 && woWPartyMember.GroupNumber == 2 ||
                            THSettings.Instance.Group4 && woWPartyMember.GroupNumber == 3 ||
                            THSettings.Instance.Group5 && woWPartyMember.GroupNumber == 4 ||
                            THSettings.Instance.Group6 && woWPartyMember.GroupNumber == 5 ||
                            THSettings.Instance.Group7 && woWPartyMember.GroupNumber == 6 ||
                            THSettings.Instance.Group8 && woWPartyMember.GroupNumber == 7)
                        {
                            Logging.Write("Add " + woWPartyMember.ToPlayer().Class + " in Group: " +
                                          (Convert.ToByte(woWPartyMember.GroupNumber) + 1) +
                                          " to Selective Group Healing");
                            GroupHealingMembers.Add(woWPartyMember.ToPlayer());
                        }
                    }
                }

                if (GroupHealingMembers.Any())
                {
                    Logging.Write("----------------------------------");
                    Logging.Write("You are assigned to Heal " + GroupHealingMembers.Count() + " Members");
                    Logging.Write("You will also heal your Target, your Focus and Yourself!");
                    Logging.Write("----------------------------------");
                }
            }
        }

        #endregion

        #region UpdateMyLatency

        public static double MyLatency;

        public static void UpdateMyLatency()
        {
            if (THSettings.Instance.LagTolerance)
            {
                //If SLagTolerance enabled, start casting next spell MyLatency Millisecond before GlobalCooldown ready.

                MyLatency = (StyxWoW.WoWClient.Latency);
                //MyLatency = 0;
                //Use here because Lag Tolerance cap at 400
                //Logging.Write("----------------------------------");
                //Logging.Write("MyLatency: " + MyLatency);
                //Logging.Write("----------------------------------");

                if (MyLatency > 400)
                {
                    //Lag Tolerance cap at 400
                    MyLatency = 400;
                }
            }
            else
            {
                MyLatency = 0;
            }
        }

        #endregion

        #region UpdateMyTalent

        private static string _hasTalent = "";

        private void UpdateMyTalentEvent(object sender, LuaEventArgs args)
        {
            UpdateMyTalent();
        }

        public int ParalysisBonusRange;

        public void UpdateMyTalent()
        {
            _hasTalent = "";
            for (int i = 1; i <= 18; i++)
            {
                _hasTalent = _hasTalent +
                             Lua.GetReturnVal<String>(
                                 string.Format(
                                     "local t= select(5,GetTalentInfo({0})) if t == true then return '['..select(1,GetTalentInfo({0}))..'] ' end return nil",
                                     i), 0);
            }

            ParalysisBonusRange = 0;
            if (SpellManager.HasSpell("Deadly Reach"))
            {
                ParalysisBonusRange = 15;
            }

            Logging.Write("----------------------------------");
            Logging.Write("Talent:");
            Logging.Write(_hasTalent);
            Logging.Write("----------------------------------");
            _hasTalent = "";
        }

        #endregion

        #region UseHealthstone

        private Composite UseHealthstone()
        {
            return
                new Decorator(
                    ret =>
                    THSettings.Instance.HealthStone &&
                    THSettings.Instance.HealthStoneHP != 0 &&
                    Me.Combat &&
                    Me.HealthPercent < THSettings.Instance.HealthStoneHP &&
                    Me.CurrentTarget != null &&
                    Me.CurrentTarget.CurrentHealth > Me.HealthPercent,
                    new Action(delegate
                                   {
                                       WoWItem hs = Me.BagItems.FirstOrDefault(o => o.Entry == 5512); //5512 Healthstone
                                       if (hs != null && hs.CooldownTimeLeft.TotalMilliseconds <= MyLatency)
                                       {
                                           hs.Use();
                                           //Lua.DoString("RunMacroText(\"/s Used Healthstone\")");
                                           Logging.Write("Use Healthstone at " + Me.HealthPercent + "%");
                                       }
                                       return RunStatus.Failure;
                                   })
                    );
        }

        #endregion

        #region UpdateCooldown

        //private DateTime _expelHarmCooldown;
        //private DateTime _risingSunKickCoolDown;
        //private DateTime _fistsofFuryCoolDown;
        //private DateTime _energizingBrewCooldown;
        //private DateTime _flyingSerpentKickCooldown;

        //private void UpdateCooldown(string spellName)
        //{
        //    switch (spellName)
        //    {
        //        case "Expel Harm":
        //            _expelHarmCooldown = DateTime.Now + SpellManager.Spells[spellName].CooldownTimeLeft -
        //                                 TimeSpan.FromMilliseconds(MyLatency);
        //            break;
        //        case "Rising Sun Kick":
        //            _risingSunKickCoolDown = DateTime.Now + SpellManager.Spells[spellName].CooldownTimeLeft -
        //                                     TimeSpan.FromMilliseconds(MyLatency);
        //            break;
        //        case "Fists of Fury":
        //            _fistsofFuryCoolDown = DateTime.Now + SpellManager.Spells[spellName].CooldownTimeLeft -
        //                                   TimeSpan.FromMilliseconds(MyLatency);
        //            break;
        //        case "Energizing Brew":
        //            _energizingBrewCooldown = DateTime.Now + SpellManager.Spells[spellName].CooldownTimeLeft -
        //                                      TimeSpan.FromMilliseconds(MyLatency);
        //            break;
        //        case "Flying Serpent Kick":
        //            _flyingSerpentKickCooldown = DateTime.Now + SpellManager.Spells[spellName].CooldownTimeLeft -
        //                                         TimeSpan.FromMilliseconds(MyLatency);
        //            break;
        //    }
        //}

        #endregion

        #region UpdateMyNoGCDSpell

        private static readonly HashSet<string> NoGCDSpells = new HashSet<string>();

        public void UpdateMyNoGCDSpell()
        {
            if (SpellManager.HasSpell("Arcane Torrent"))
            {
                NoGCDSpells.Add("Arcane Torrent");
            }

            if (SpellManager.HasSpell("Ardent Defender"))
            {
                NoGCDSpells.Add("Ardent Defender");
            }

            if (SpellManager.HasSpell("Avenging Wrath"))
            {
                NoGCDSpells.Add("Avenging Wrath");
            }

            if (HasGlyph.Contains("63218"))
            {
                NoGCDSpells.Add("Beacon of Light");
            }

            if (SpellManager.HasSpell("Devotion Aura"))
            {
                NoGCDSpells.Add("Devotion Aura");
            }

            if (SpellManager.HasSpell("Divine Favor"))
            {
                NoGCDSpells.Add("Divine Favor");
            }

            if (SpellManager.HasSpell("Divine Protection"))
            {
                NoGCDSpells.Add("Divine Protection");
            }

            if (SpellManager.HasSpell("Guardian of Ancient Kings"))
            {
                NoGCDSpells.Add("Guardian of Ancient Kings");
            }

            if (SpellManager.HasSpell("Holy Avenger"))
            {
                NoGCDSpells.Add("Holy Avenger");
            }

            if (SpellManager.HasSpell("Lay on Hands"))
            {
                NoGCDSpells.Add("Lay on Hands");
            }

            if (SpellManager.HasSpell("Rebuke"))
            {
                NoGCDSpells.Add("Rebuke");
            }

            if (SpellManager.HasSpell("Reckoning"))
            {
                NoGCDSpells.Add("Reckoning");
            }


            Logging.Write("----------------------------------");
            Logging.Write("Spells that don't use Global Cooldown:");
            foreach (string spell in NoGCDSpells)
            {
                Logging.Write(" -" + spell);
            }
            Logging.Write("----------------------------------");
        }

        #endregion

        #region UpdateMyGlyph

        public void UpdateMyGlyphEvent(object sender, LuaEventArgs args)
        {
            UpdateMyGlyph();
        }

        //private static readonly HashSet<string> NoGCDSpells = new HashSet<string> { };
        public string HasGlyph;
        public string HasGlyphName;
        public int TouchofKarmaBonusRange;
        public int ExpelHarmBonusRange;
        public int TranscendenceRangeBonus;

        public void UpdateMyGlyph()
        {
            HasGlyph = "";
            HasGlyphName = "";

            var glyphCount = Lua.GetReturnVal<int>("return GetNumGlyphSockets()", 0);

            if (glyphCount != 0)
            {
                for (int i = 1; i <= glyphCount; i++)
                {
                    string lua =
                        String.Format(
                            "local enabled, glyphType, glyphTooltipIndex, glyphSpellID, icon = GetGlyphSocketInfo({0});if (enabled) then return glyphSpellID else return 0 end",
                            i);

                    var glyphSpellId = Lua.GetReturnVal<int>(lua, 0);

                    try
                    {
                        if (glyphSpellId > 0)
                        {
                            HasGlyphName = HasGlyphName + "[" + (WoWSpell.FromId(glyphSpellId)) + " - " + glyphSpellId +
                                           "] ";
                            HasGlyph = HasGlyph + "[" + glyphSpellId + "] ";
                        }
                        else
                        {
                            Logging.Write("Glyphdetection - No Glyph in slot " + i);
                            //TreeRoot.Stop();
                        }
                    }
                    catch (Exception ex)
                    {
                        Logging.Write("We couldn't detect your Glyphs");
                        Logging.Write("Report this message to us: " + ex);
                        //TreeRoot.Stop();
                    }
                }
            }
            TouchofKarmaBonusRange = 0;
            if (HasGlyph.Contains("[" + 125678 + "]"))
            {
                TouchofKarmaBonusRange = 15;
            }

            ExpelHarmBonusRange = 0;
            if (HasGlyph.Contains("[" + 119724 + "]"))
            {
                ExpelHarmBonusRange = 10;
            }

            TranscendenceRangeBonus = 0;
            if (HasGlyph.Contains("[" + 123023 + "]"))
            {
                ExpelHarmBonusRange = 10;
            }
            Logging.Write("----------------------------------");
            Logging.Write("Glyph:");
            Logging.Write(HasGlyphName);
            Logging.Write("----------------------------------");
        }

        #endregion

        #region UpdatePvPSet

        public int PvPPieceWindWalker;

        public void UpdatePvPSet()
        {
            PvPPieceWindWalker = 0;

            if (Me.Inventory.Equipped.Head != null && Me.Inventory.Equipped.Head.Name.Contains("Gladiator's Ironskin"))
            {
                PvPPieceWindWalker = PvPPieceWindWalker + 1;
            }

            if (Me.Inventory.Equipped.Shoulder != null &&
                Me.Inventory.Equipped.Shoulder.Name.Contains("Gladiator's Ironskin"))
            {
                PvPPieceWindWalker = PvPPieceWindWalker + 1;
            }

            if (Me.Inventory.Equipped.Chest != null && Me.Inventory.Equipped.Chest.Name.Contains("Gladiator's Ironskin"))
            {
                PvPPieceWindWalker = PvPPieceWindWalker + 1;
            }

            if (Me.Inventory.Equipped.Hands != null && Me.Inventory.Equipped.Hands.Name.Contains("Gladiator's Ironskin"))
            {
                PvPPieceWindWalker = PvPPieceWindWalker + 1;
            }

            if (Me.Inventory.Equipped.Legs != null && Me.Inventory.Equipped.Legs.Name.Contains("Gladiator's Ironskin"))
            {
                PvPPieceWindWalker = PvPPieceWindWalker + 1;
            }
            BonusFistsofFuryRange = 0;
            if (PvPPieceWindWalker >= 4)
            {
                BonusFistsofFuryRange = 4;
            }

            Logging.Write("----------------------------------");
            Logging.Write("You Have: " + PvPPieceWindWalker + " Piece PvP Set Gladiator's Ironskin");
            Logging.Write("----------------------------------");
        }

        #endregion

        #region UpdateStatus

        public void UpdateStatus()
        {
            if (THSettings.Instance.UpdateStatus)
                if (Me.IsValid)
                {
                    {
                        GetCurrentSpec();

                        //Reset BurstLast on start
                        BurstLast = DateTime.Now;

                        //if (THSettings.Instance.SLastSavedSpec != THForm.GetCurrentSpec())
                        //{
                        //    Logging.Write("----------------------------------");
                        //    Logging.Write("You just change specialization to " + THForm.GetCurrentSpec());
                        //    Logging.Write("Please select the appropriate settings");
                        //    Logging.Write("----------------------------------");
                        //    OnButtonPress();
                        //}

                        Logging.Write("----------------------------------");
                        Logging.Write("Building Rotation base on current Talents and Glyphs......");
                        Logging.Write("----------------------------------");
                        Logging.Write("");

                        //if (TreeRoot.Current.Name != "Questing" && 
                        //    TreeRoot.Current.Name != "Grind Bot" &&
                        //    TreeRoot.Current.Name != "LazyRaider" && 
                        //    TreeRoot.Current.Name != "BGBuddy" &&
                        //    TreeRoot.Current.Name != "DungeonBuddy" && 
                        //    TreeRoot.Current.Name != "Mixed Mode" && 
                        //    GetAsyncKeyState(Keys.F10) == 0)
                        //{
                        //    Logging.Write("This CC only work with DungeonBuddy - LazyRaider - Questing - Grind Bot.");
                        //    Logging.Write("Custom Class Stop.");

                        //    TreeRoot.Stop();
                        //}

                        if (TreeRoot.Current.Name == "LazyRaider" && !THSettings.Instance.AutoMove)
                        {
                            THSettings.Instance.AutoMove = false;
                            //Logging.Write(LogLevel.Diagnostic,
                            //              "EnableMovement: " + THSettings.Instance.EnableMovement);
                        }
                        //else
                        //{
                        //    THSettings.Instance.SMoveToTarget = true;
                        //    THSettings.Instance.SAutoTarget = true;
                        //Logging.Write(LogLevel.Diagnostic,
                        //              "EnableMovement: " + THSettings.Instance.EnableMovement);
                        //}

                        //if (Me.Level < 85)
                        //{
                        //    Logging.Write("This CC only work on Level 85-90.");
                        //    //TreeRoot.Stop();
                        //    return;
                        //}


                        //ReadXML();

                        UpdateMyTalent();

                        UpdateMyGlyph();

                        UpdateMyNoGCDSpell();

                        UpdateMyLatency();

                        UpdatePvPSet();

                        UpdateGroupHealingMembers();

                        _gcdReady = DateTime.Now;
                        Logging.Write("----------------------------------");
                        Logging.Write("Building Rotation Completed");
                        Logging.Write("----------------------------------");
                        Logging.Write("");

                        Logging.Write("----------------------------------");
                        Logging.Write("Press Control + " + IndexToKeys(THSettings.Instance.PauseKey) +
                                      " To Toggle Pause Mode.");
                        Logging.Write("----------------------------------");
                        Logging.Write("");

                        Logging.Write("----------------------------------");
                        Logging.Write("Press Control + " + IndexToKeys(THSettings.Instance.AoEKey) +
                                      " To Toggle AoE Mode (BrewMaster and WindWalker only)");
                        Logging.Write("----------------------------------");
                        Logging.Write("");

                        if (THSettings.Instance.BurstKey > 6)
                        {
                            Logging.Write("----------------------------------");
                            Logging.Write("Press Control + " + IndexToKeys(THSettings.Instance.BurstKey - 6) +
                                          " To Toggle Burst Mode");
                            Logging.Write("----------------------------------");
                            Logging.Write("");
                        }
                        THSettings.Instance.UpdateStatus = false;
                    }
                }
        }

        #endregion

        #region ValidUnit

        public bool ValidUnit(WoWUnit u)
        {
            if (u == null || !u.IsValid || !u.Attackable || !u.IsAlive || u.IsDead || !u.CanSelect ||
                u.IsCritter && (u.CurrentTarget == null || u.CurrentTarget != null && u.CurrentTarget != Me) ||
                u.IsNonCombatPet || Blacklist.Contains(u.Guid, BlacklistFlags.All))
            {
                return false;
            }
            return true;
        }

        #endregion
    }
}